From 3d779e3f0797bfc7e3e8b270b5de7736dc22ff12 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 13 Nov 2003 17:09:34 +0000 Subject: [PATCH] bitkeeper revision 1.603 (3fb3bacevrb8jueJUVr6_fTdAFNH3A) ac_timer.h, schedule.c, network.c, ac_timer.c: Cleaned up ac_timer interface, and fixed a bug in the softirq handler. --- xen/common/ac_timer.c | 16 ++++--- xen/common/network.c | 2 +- xen/common/schedule.c | 9 ++-- xen/include/xeno/ac_timer.h | 84 +++++++++++++++++++++++-------------- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/xen/common/ac_timer.c b/xen/common/ac_timer.c index e456e83624..c3d2f51b37 100644 --- a/xen/common/ac_timer.c +++ b/xen/common/ac_timer.c @@ -246,6 +246,7 @@ static void ac_timer_softirq_action(struct softirq_action *a) int cpu = smp_processor_id(); struct ac_timer *t, **heap; s_time_t now; + void (*fn)(unsigned long); spin_lock_irq(&ac_timers[cpu].lock); @@ -257,12 +258,15 @@ static void ac_timer_softirq_action(struct softirq_action *a) ((t = heap[1])->expires < (now + TIMER_SLOP)) ) { remove_entry(heap, t); - - spin_unlock_irq(&ac_timers[cpu].lock); - if ( t->function != NULL ) - t->function(t->data); - spin_lock_irq(&ac_timers[cpu].lock); - + + if ( (fn = t->function) != NULL ) + { + unsigned long data = t->data; + spin_unlock_irq(&ac_timers[cpu].lock); + (*fn)(data); + spin_lock_irq(&ac_timers[cpu].lock); + } + /* Heap may have grown while the lock was released. */ heap = ac_timers[cpu].heap; } diff --git a/xen/common/network.c b/xen/common/network.c index 367790644a..02b6f57580 100644 --- a/xen/common/network.c +++ b/xen/common/network.c @@ -107,7 +107,7 @@ net_vif_t *create_net_vif(int domain) new_vif->credit_bytes = new_vif->remaining_credit = ~0UL; new_vif->credit_usec = 0UL; - init_ac_timer(&new_vif->credit_timeout, 0); + init_ac_timer(&new_vif->credit_timeout); if ( (p->domain == 0) && (dom_vif_idx == 0) ) { diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 5f22ec8013..5997b276a2 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -613,18 +613,21 @@ void __init scheduler_init(void) spin_lock_init(&schedule_data[i].lock); schedule_data[i].curr = &idle0_task; - init_ac_timer(&schedule_data[i].s_timer, i); + init_ac_timer(&schedule_data[i].s_timer); + schedule_data[i].s_timer.cpu = i; schedule_data[i].s_timer.data = 2; schedule_data[i].s_timer.function = &sched_timer; - init_ac_timer(&fallback_timer[i], i); + init_ac_timer(&fallback_timer[i]); + fallback_timer[i].cpu = i; fallback_timer[i].data = 0; fallback_timer[i].function = &fallback_timer_fn; } schedule_data[0].idle = &idle0_task; - init_ac_timer(&v_timer, 0); + init_ac_timer(&v_timer); + v_timer.cpu = 0; v_timer.data = 0; v_timer.function = &virt_timer; } diff --git a/xen/include/xeno/ac_timer.h b/xen/include/xeno/ac_timer.h index 987fbeed33..3689662e95 100644 --- a/xen/include/xeno/ac_timer.h +++ b/xen/include/xeno/ac_timer.h @@ -20,52 +20,72 @@ #ifndef _AC_TIMER_H_ #define _AC_TIMER_H_ -#include /* include notion of time */ - -/* - * The Xen Hypervisor provides two types of timers: - * - * - Linux style, jiffy based timers for legacy code and coarse grain timeouts - * These are defined in ./include/xeno/timer.h and implemented in - * ./common/timer.c. Unlike in Linux they are executed not on a periodic - * timer interrupt but "occasionally" with somewhat lesser accuracy. - * - * - accurate timers defined in this file and implemented in - * ./common/ac_timer.c. These are implemented using a programmable timer - * interrupt and are thus as accurate as the hardware allows. Where possible - * we use the local APIC for this purpose. However, this fact is hidden - * behind a architecture independent layer. - * accurate timers are programmed using system time. - * - * The interface to accurate timers is very similar to Linux timers with the - * exception that the expires value is not expressed in jiffies but in ns from - * boot time. Its implementation however, is entirely different. - */ +#include struct ac_timer { - s_time_t expires; /* system time time out value */ + /* + * PUBLIC FIELDS + */ + /* System time expiry value (nanoseconds since boot). */ + s_time_t expires; + /* CPU on which this timer will be installed and executed. */ + unsigned int cpu; + /* On expiry, '(*function)(data)' will be executed in softirq context. */ unsigned long data; void (*function)(unsigned long); - unsigned int cpu; + + /* + * PRIVATE FIELDS + */ unsigned int heap_offset; }; -/* interface for "clients" */ -extern void add_ac_timer(struct ac_timer *timer); -extern void rem_ac_timer(struct ac_timer *timer); -extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time); -static __inline__ void init_ac_timer(struct ac_timer *timer, int cpu) +/* + * This function can be called for any CPU from any CPU in any context. + * It initialises the private fields of the ac_timer structure. + */ +static __inline__ void init_ac_timer(struct ac_timer *timer) { - timer->cpu = cpu; timer->heap_offset = 0; } -/* check if ac_timer is active, i.e., on the list */ + +/* + * This function can be called for any CPU from any CPU in any context. + * It returns TRUE if the given timer is on a timer list. + */ static __inline__ int active_ac_timer(struct ac_timer *timer) { return (timer->heap_offset != 0); } -/* interface used by programmable timer, implemented hardware dependent */ -extern int reprogram_ac_timer(s_time_t timeout); +/* + * This function can be called for any CPU from any CPU in any context, BUT: + * -- The private fields must have been initialised (ac_timer_init). + * -- All public fields must be initialised. + * -- The timer must not currently be on a timer list. + */ +extern void add_ac_timer(struct ac_timer *timer); + +/* + * This function can be called for any CPU from any CPU in any context, BUT: + * -- The private fields must have been initialised (ac_timer_init). + * -- All public fields must be initialised. + * -- The timer must currently be on a timer list. + */ +extern void rem_ac_timer(struct ac_timer *timer); + +/* + * This function can be called for any CPU from any CPU in any context, BUT: + * -- The private fields must have been initialised (ac_timer_init). + * -- All public fields must be initialised. + */ +extern void mod_ac_timer(struct ac_timer *timer, s_time_t new_time); + + +/* + * PRIVATE DEFINITIONS + */ + +extern int reprogram_ac_timer(s_time_t timeout); #endif /* _AC_TIMER_H_ */ -- 2.30.2